1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7 /*
8 * Source:
9 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17
10 */
11
12 package com.google.common.cache;
13
14 import com.google.common.annotations.GwtCompatible;
15
16 import java.io.IOException;
17 import java.io.ObjectInputStream;
18 import java.io.ObjectOutputStream;
19 import java.io.Serializable;
20 import java.util.concurrent.atomic.AtomicLong;
21
22 /**
23 * One or more variables that together maintain an initially zero
24 * {@code long} sum. When updates (method {@link #add}) are contended
25 * across threads, the set of variables may grow dynamically to reduce
26 * contention. Method {@link #sum} (or, equivalently, {@link
27 * #longValue}) returns the current total combined across the
28 * variables maintaining the sum.
29 *
30 * <p>This class is usually preferable to {@link AtomicLong} when
31 * multiple threads update a common sum that is used for purposes such
32 * as collecting statistics, not for fine-grained synchronization
33 * control. Under low update contention, the two classes have similar
34 * characteristics. But under high contention, expected throughput of
35 * this class is significantly higher, at the expense of higher space
36 * consumption.
37 *
38 * <p>This class extends {@link Number}, but does <em>not</em> define
39 * methods such as {@code equals}, {@code hashCode} and {@code
40 * compareTo} because instances are expected to be mutated, and so are
41 * not useful as collection keys.
42 *
43 * <p><em>jsr166e note: This class is targeted to be placed in
44 * java.util.concurrent.atomic.</em>
45 *
46 * @since 1.8
47 * @author Doug Lea
48 */
49 @GwtCompatible(emulated = true)
50 final class LongAdder extends Striped64 implements Serializable, LongAddable {
51 private static final long serialVersionUID = 7249069246863182397L;
52
53 /**
54 * Version of plus for use in retryUpdate
55 */
56 final long fn(long v, long x) { return v + x; }
57
58 /**
59 * Creates a new adder with initial sum of zero.
60 */
61 public LongAdder() {
62 }
63
64 /**
65 * Adds the given value.
66 *
67 * @param x the value to add
68 */
69 public void add(long x) {
70 Cell[] as; long b, v; int[] hc; Cell a; int n;
71 if ((as = cells) != null || !casBase(b = base, b + x)) {
72 boolean uncontended = true;
73 if ((hc = threadHashCode.get()) == null ||
74 as == null || (n = as.length) < 1 ||
75 (a = as[(n - 1) & hc[0]]) == null ||
76 !(uncontended = a.cas(v = a.value, v + x)))
77 retryUpdate(x, hc, uncontended);
78 }
79 }
80
81 /**
82 * Equivalent to {@code add(1)}.
83 */
84 public void increment() {
85 add(1L);
86 }
87
88 /**
89 * Equivalent to {@code add(-1)}.
90 */
91 public void decrement() {
92 add(-1L);
93 }
94
95 /**
96 * Returns the current sum. The returned value is <em>NOT</em> an
97 * atomic snapshot; invocation in the absence of concurrent
98 * updates returns an accurate result, but concurrent updates that
99 * occur while the sum is being calculated might not be
100 * incorporated.
101 *
102 * @return the sum
103 */
104 public long sum() {
105 long sum = base;
106 Cell[] as = cells;
107 if (as != null) {
108 int n = as.length;
109 for (int i = 0; i < n; ++i) {
110 Cell a = as[i];
111 if (a != null)
112 sum += a.value;
113 }
114 }
115 return sum;
116 }
117
118 /**
119 * Resets variables maintaining the sum to zero. This method may
120 * be a useful alternative to creating a new adder, but is only
121 * effective if there are no concurrent updates. Because this
122 * method is intrinsically racy, it should only be used when it is
123 * known that no threads are concurrently updating.
124 */
125 public void reset() {
126 internalReset(0L);
127 }
128
129 /**
130 * Equivalent in effect to {@link #sum} followed by {@link
131 * #reset}. This method may apply for example during quiescent
132 * points between multithreaded computations. If there are
133 * updates concurrent with this method, the returned value is
134 * <em>not</em> guaranteed to be the final value occurring before
135 * the reset.
136 *
137 * @return the sum
138 */
139 public long sumThenReset() {
140 long sum = base;
141 Cell[] as = cells;
142 base = 0L;
143 if (as != null) {
144 int n = as.length;
145 for (int i = 0; i < n; ++i) {
146 Cell a = as[i];
147 if (a != null) {
148 sum += a.value;
149 a.value = 0L;
150 }
151 }
152 }
153 return sum;
154 }
155
156 /**
157 * Returns the String representation of the {@link #sum}.
158 * @return the String representation of the {@link #sum}
159 */
160 public String toString() {
161 return Long.toString(sum());
162 }
163
164 /**
165 * Equivalent to {@link #sum}.
166 *
167 * @return the sum
168 */
169 public long longValue() {
170 return sum();
171 }
172
173 /**
174 * Returns the {@link #sum} as an {@code int} after a narrowing
175 * primitive conversion.
176 */
177 public int intValue() {
178 return (int)sum();
179 }
180
181 /**
182 * Returns the {@link #sum} as a {@code float}
183 * after a widening primitive conversion.
184 */
185 public float floatValue() {
186 return (float)sum();
187 }
188
189 /**
190 * Returns the {@link #sum} as a {@code double} after a widening
191 * primitive conversion.
192 */
193 public double doubleValue() {
194 return (double)sum();
195 }
196
197 private void writeObject(ObjectOutputStream s) throws IOException {
198 s.defaultWriteObject();
199 s.writeLong(sum());
200 }
201
202 private void readObject(ObjectInputStream s)
203 throws IOException, ClassNotFoundException {
204 s.defaultReadObject();
205 busy = 0;
206 cells = null;
207 base = s.readLong();
208 }
209
210 }